package cn.edu.zut.soft.graduate.topicCenter.bo.impl;

import cn.edu.zut.soft.basic.core.constant.Alternative;
import cn.edu.zut.soft.basic.core.model.dao.Criteria;
import cn.edu.zut.soft.basic.core.model.dao.Example;
import cn.edu.zut.soft.graduate.base.bo.BasicBOImpl;
import cn.edu.zut.soft.graduate.base.dao.BasicDAO;
import cn.edu.zut.soft.graduate.core.constant.*;
import cn.edu.zut.soft.graduate.core.constant.config.IKEY;
import cn.edu.zut.soft.graduate.core.design.BasicInfoStrategy;
import cn.edu.zut.soft.graduate.core.design.InfoStrategy;
import cn.edu.zut.soft.graduate.core.model.Impl.Declare;
import cn.edu.zut.soft.graduate.core.model.Impl.Group;
import cn.edu.zut.soft.graduate.core.model.Impl.Info;
import cn.edu.zut.soft.graduate.core.model.Impl.Issue;
import cn.edu.zut.soft.graduate.core.query.DeclareQuery;
import cn.edu.zut.soft.graduate.core.query.IssueQuery;
import cn.edu.zut.soft.graduate.core.vo.LoginVO;
import cn.edu.zut.soft.graduate.groupCenter.bo.GroupBO;
import cn.edu.zut.soft.graduate.topicCenter.bo.CompanyProjectRequestBO;
import cn.edu.zut.soft.graduate.topicCenter.bo.DeclareBO;
import cn.edu.zut.soft.graduate.topicCenter.bo.IssueBO;
import cn.edu.zut.soft.graduate.topicCenter.dao.DeclareDAO;
import cn.edu.zut.soft.graduate.topicCenter.handler.exception.HandlerException;
import cn.edu.zut.soft.graduate.topicCenter.op.DeclareOP;
import cn.edu.zut.soft.graduate.topicCenter.pojo.ConfirmInfo;
import cn.edu.zut.soft.graduate.topicCenter.pojo.DeclareInfo;
import cn.edu.zut.soft.graduate.userCenter.bo.InfoBO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Transformer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.*;

/**
 * @author chuchuang
 * @date 16/11/27
 */
@Component
public class DeclareBOImpl extends BasicBOImpl<Declare, DeclareQuery> implements DeclareBO {

    @Autowired
    private DeclareDAO<Declare> declareDAO;

    @Autowired
    private InfoBO infoBO;

    @Autowired
    private GroupBO groupBO;

    @Autowired
    private IssueBO issueBO;

    @Autowired
    private DeclareOP declareOP;

    @Autowired
    private CompanyProjectRequestBO companyProjectRequestBO;

    private static final List<IssuePhase> findDeclareIssuePhase = Arrays.asList(IssuePhase.saveIng,IssuePhase.auditIng,IssuePhase.auditErrorIng,IssuePhase.chooseIng, IssuePhase.finish);

    @Override
    protected BasicDAO<Integer, Declare> getDAO() {
        return declareDAO;
    }

    @Override
    protected List<Criteria> Query(DeclareQuery declareQuery) {
        Criteria criteria = new Criteria();
        if (declareQuery.getId() != null) {
            criteria.andEqualTo("id", declareQuery.getId());
        }
        if (declareQuery.getGroupId() != null) {
            criteria.andEqualTo("group_id", declareQuery.getGroupId());
        }
        if (declareQuery.getStatus() != null) {
            criteria.andEqualTo("`status`", declareQuery.getStatus().name());
        }
        if (CollectionUtils.isNotEmpty(declareQuery.getDeclareStatusList())) {
            criteria.andIn("`status`", declareQuery.getDeclareStatusList());
        }
        if (declareQuery.getTopicId() != null) {
            criteria.andEqualTo("topic_id", declareQuery.getTopicId());
        }
        if (declareQuery.getDel() != null) {
            criteria.andEqualTo("del", declareQuery.getDel());
        } else {
            criteria.andEqualTo("del", IKEY.ZERO);
        }
        if (CollectionUtils.isNotEmpty(declareQuery.getIds())) {
            criteria.andIn("id", declareQuery.getIds());
        }
        return Collections.singletonList(criteria);
    }

    @Override
    public Declare GroupDeclare(LoginVO loginVO, Issue issue) {
        return declareOP.GroupDeclare(loginVO, issue);
    }

    @Override
    public boolean isAsk(LoginVO loginVO, Issue issue) {
        Assert.notNull(loginVO);
        Assert.notNull(issue);
        List<Info> infoList = infoBO.queryByUserInfoStrategy(loginVO.getId(), Collections.<InfoStrategy>singletonList(new BasicInfoStrategy(InfoType.Group, IKEY.GROUP, "")));
        Assert.notEmpty(infoList, "用户不存在小组");
        Assert.isTrue(infoList.size() < 2, "数据异常,请联系管理员");
        //传递数据用
        loginVO.setInfoList(infoList);
        Group group = groupBO.get(Integer.parseInt(infoList.get(0).getValue()));
        Assert.notNull(group, "小组错误,请联系管理员");
        Assert.isTrue(group.getDel() == IKEY.ZERO, "小组已经删除");
        Assert.isTrue(group.getIdentityId().equals(loginVO.getId()), "不是组长,无法操作");

        //是否申请了公司项目
        Assert.isTrue(!companyProjectRequestBO.isSendCompany(group.getId()),"申请了自拟题目无法申请校内题目");

        DeclareQuery declareQuery = new DeclareQuery();
        declareQuery.setGroupId(group.getId());
        declareQuery.setDeclareStatusList(Arrays.asList(DeclareStatus.ING, DeclareStatus.YES));
        //不需要事务
        int count = countByQuery(declareQuery);
        Assert.isTrue(count == 0, "小组存在课题");
        //验证课题是否能够选报
        issue = issueBO.get(issue.getId());
        Assert.notNull(issue, "课题不存在");
        Assert.isTrue(issue.getDel() == IKEY.ZERO, "课题已经删除");
        Assert.isTrue(issue.getStatus() == IssuePhase.chooseIng, "课题状态错误,无法进行选报");
        //风险数据错误时,会出现错误

        Assert.isTrue(group.getCount().equals(issue.getTaskSize()), "课题人数不匹配");

        return true;
    }

    @Override
    public List<DeclareInfo> findDeclareInfo(DeclareQuery declareQuery) {
        List<Declare> declareList = findByQuery(declareQuery).getData();
        if (CollectionUtils.isEmpty(declareList)) {
            return Collections.emptyList();
        }
        List<Integer> ids = new ArrayList<>(declareList.size());
        CollectionUtils.collect(declareList, new Transformer() {
            @Override
            public Object transform(Object o) {
                return ((Declare) o).getTopicId();
            }
        }, ids);
        List<DeclareInfo> declareInfoList = new ArrayList<>(declareList.size());
        IssueQuery issueQuery = new IssueQuery();
        issueQuery.setPageSize(declareQuery.getPageSize());
        issueQuery.setIds(ids);
        issueQuery.setIssuePhaseList(findDeclareIssuePhase);
        List<Issue> issueList = issueBO.findByQuery(issueQuery).getData();
        Map<Integer,Issue> issueMap = new HashMap<>();
        for (Issue issue : issueList){
            issueMap.put(issue.getId(),issue);
        }

        DeclareInfo declareInfo;
        for (Declare declare : declareList) {
            declareInfo = new DeclareInfo();
            declareInfo.setDeclare(declare);
            declareInfo.setInfoList(infoBO.queryByInfoStrategy(Collections.<InfoStrategy>singletonList(new BasicInfoStrategy(InfoType.Group,IKEY.GROUP,declare.getGroupId().toString()))));
            declareInfo.setIssue(issueMap.get(declare.getTopicId()));
            declareInfoList.add(declareInfo);
        }
//        CollectionUtils.collect(declareList, new Transformer() {
//            @Override
//            public Object transform(Object o) {
//                return ((Declare)o).getTopicId();
//            }
//        },ids);

//        DeclareInfo declareInfo;
//        for (Declare declare : declareList){
//            declareInfo = new DeclareInfo();
//            declareInfo.setDeclare(declare);
//            declareInfo.setIssue(issueMap.get(declare.getTopicId()));
//            declareInfoList.add(declareInfo);
//        }
        return declareInfoList;
    }

    /**
     * 1.拒绝所有申报记录
     * 2.同意当前申报记录
     *
     * @param confirmInfo
     * @return
     */
    public ConfirmInfo Confirm(ConfirmInfo confirmInfo) {
        Assert.notNull(confirmInfo.getDeclareOk(), "同意的记录不存在");
        Example example = new Example();
        example.createCriteria().andEqualTo("topic_id", confirmInfo.getIssue().getId()).andNotEqualTo("id", confirmInfo.getDeclareOk().getId()).andEqualTo("del", IKEY.ZERO);
        //采用检索条件直接更新的方法
        confirmInfo.setRefuseList(getDAO().selectByExample(example));
        Declare declare = new Declare();
        declare.setStatus(DeclareStatus.NO);
        declare.setUpdateAuthor(confirmInfo.getLoginVO().getName());
        getDAO().updateByExampleSelective(declare, example);
        confirmInfo.getDeclareOk().setStatus(DeclareStatus.YES);
        getDAO().updateByPrimaryKeySelective(confirmInfo.getDeclareOk());
        return confirmInfo;
    }

    @Override
    public List<Declare> deleteByGroupId(Integer id, String operator) {
        Example example = new Example();
        example.createCriteria().andEqualTo("group_id",id).andEqualTo("del",IKEY.ZERO);
        List<Declare> declareList = getDAO().selectByExample(example);
        Declare declare = new Declare();
        declare.setStatus(DeclareStatus.NO);
        declare.setDel(-1);
        declare.setUpdateAuthor(operator);
        getDAO().updateByExampleSelective(declare,example);
        return declareList;
    }

    @Override
    public ConfirmInfo TeaConfirm(LoginVO loginVO, Integer declareId, Alternative alternative) {
        Assert.notNull(loginVO);
        Assert.notNull(declareId);
        Assert.notNull(alternative);

        Declare declare = get(declareId);
        Assert.notNull(declare, "操作记录不存在");
        Assert.isTrue(declare.getDel() == IKEY.ZERO, "链接状态错误");
        Assert.isTrue(declare.getStatus() == DeclareStatus.ING, "当前状态不能够操作");

        Issue issue = issueBO.get(declare.getTopicId());
        Assert.notNull(issue, "课题不存在");
        //课题必须是有效切为选报中才具有权限
        Assert.isTrue(issue.getDel() == IKEY.ZERO && issue.getStatus() == IssuePhase.chooseIng, "课题状态无权进行当前操作");
        Assert.isTrue(issue.getIdentityRole() == Role.tea && issue.getSource() == IssueSource.school, "非校内课题,无权操作");
        Assert.isTrue(issue.getIdentityId().equals(loginVO.getId()), "非操作者创建课题,无权操作");
        //选报小组
        Group group = groupBO.get(declare.getGroupId());
        Assert.notNull(group, "小组不存在");
        if (Alternative.YES == alternative) {
            Assert.isTrue(group.getCount().equals(issue.getTaskSize()), "课题与学生小组人数不符");
            Assert.isTrue(group.getDel() == IKEY.ZERO, "学生小组不存在");
            Assert.isTrue(group.getStatus() == IssueSource.school, "学生小组申报自拟题目,无法同意");
            Assert.isTrue(group.getRole() == Role.stu, "小组角色不符合要求");
        }
        //封装对象
        ConfirmInfo confirmInfo = new ConfirmInfo();
        confirmInfo.setLoginVO(loginVO);
        confirmInfo.setAlternative(alternative);
        confirmInfo.setDeclareOk(declare);
        confirmInfo.setIssue(issue);
        confirmInfo.setGroup(group);
        //操作
        declareOP.TeaConfirm(confirmInfo);
        return confirmInfo;
    }

}
